<script setup lang="ts">
import {devSelectProps} from './select';
import {computed, onActivated, onMounted, ref, useAttrs, useSlots, watch} from 'vue';
import {devDeepMerge, devIsObjectArray, useConfig} from "@/index";
import {useDevMethods} from '@/utils/methodProvider';
import {ElOption, ElSelect} from "element-plus";
import { isEqual } from 'lodash-es'

const slots = useSlots();
const attrs = useAttrs(); // 事件和属性
const props = defineProps(devSelectProps); // 组件props
const options_ = ref<any[]>([]); // 下拉选项
const emit = defineEmits(['options-data']); // 组件事件
const methods = useDevMethods();

// 下拉选项默认配置
const computedSelectProps = computed(() => devDeepMerge(useConfig().elSelectProps, attrs));

const optionObj = ref<Record<string, any>>({});//存储需要绑定的对象信息

/**
 * 处理选项信息
 * @param list
 */
const handlingOptions = (list: any) => {
  if (props.useModelObj && props.objMapper && typeof props.objMapper === 'object' && (Object.keys(props.objMapper).length > 0) && devIsObjectArray(list)) {
    optionObj.value = {}
    return list.map((item: any) => {
      const result: any = {};
      let sourceValueKey:any;
      for (const [targetKey, sourceKey] of Object.entries(props.objMapper)) {
        result[targetKey] = item[sourceKey];
        if(targetKey === props.optionValueKey) sourceValueKey = sourceKey;
      }
      optionObj.value[item[sourceValueKey]] = result;
      return {...item,...result};
    })
  } else {
    optionObj.value = {}
    return list || []
  }
}

/**
 * 初始化
 */
const init = () => {
  if (props.useApi && props.api) {
    props.api(props.apiParams).then((res: any) => {
      options_.value = handlingOptions(props.devSelectFieldsFn ? props.devSelectFieldsFn(res) : methods.devSelectFieldsFn(res));
      emit('options-data', options_.value)
    });
  } else {
    options_.value = handlingOptions(props.options)
    emit('options-data', options_.value)
  }
};

// 监听参数发生改变重新初始化
watch(
    () => [props.api, props.useApi, props.options],
    () => {
      init();
    }
);

// 单独监听 apiParams，但加入 isEqual 判断
watch(
    () => props.apiParams,
    (val, oldVal) => {
      if (!isEqual(val, oldVal)) {
        init();
      }
    },
    { deep: true }
);


onMounted(() => {
  if (props.onMounted && !props.onActivated) {
    init();
  }
})

onActivated(() => {
  if (props.onActivated) {
    init();
  }
})

// 定义组件名称
defineOptions({
  name: 'DevSelect',
  inheritAttrs: false
});
</script>

<template>
  <el-select
      :value-key="props.optionValueKey"
      v-bind="computedSelectProps">
    <el-option
        v-for="item in options_"
        :key="item[props.optionValueKey]"
        :label="item[props.optionLabelKey]"
        :value="props.useModelObj?(props.objMapper?optionObj[item[props.optionValueKey]]:item):item[props.optionValueKey]"
        :disabled="!!item[props.optionDisabledKey]"
    />
    <template v-for="itemSlot in Object.keys(slots)" :key="itemSlot" v-slot:[itemSlot]="temp">
      <slot :name="itemSlot" v-bind="temp"></slot>
    </template>
  </el-select>

</template>

<style scoped lang="scss">

</style>
